home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Hot Mix 17
/
Hot Mix 17.iso
/
HM17_SGI
/
research
/
examples
/
misc
/
spring.pro
< prev
next >
Wrap
Text File
|
1997-07-08
|
20KB
|
583 lines
; $Id: spring.pro,v 1.10 1997/01/15 04:21:02 ali Exp $
;
; Copyright (c) 1991-1997, Research Systems, Inc. All rights reserved.
; Unauthorized reproduction prohibited.
;+
; NAME: Spring
;
; PURPOSE: This example demonstrates the fundamental principles of statistical
; time-series analysis.
;
; MAJOR TOPICS: Surface Drawing and Widgets.
;
; CALLING SEQUENCE: Spring
;
; PROCEDURE: Spring computes ...
;
; MAJOR FUNCTIONS and PROCEDURES:
;
; COMMON BLOCKS and STRUCTURES:
; springCommon : This common block contains...
;
; MODIFICATION HISTORY: Written by: DMS, RSI, March 1991
; Modified by: WSO, RSI, January 1995
;-
;
; Return the correct color depending on the color depth used. If !D.N_COLORS
; is greater than 256, then the output device is in true color mode. If that's
; the case, we want to use the same index from the red, green and blue color
; tables to get the desired color. If it's not true color than just return
; the color table index.
;
FUNCTION GetColor, colorIndex
IF (!D.N_COLORS GT 256) THEN $
RETURN, (colorIndex * 256L + colorIndex) * 256L + colorIndex $
ELSE $
RETURN, colorIndex
END
;----------------------------------------
; Draw square in mark window at cell (x,y)
PRO MarkSquare, x, y, color
; Grid is one fifth the size of the edit area
x = x * 5
y = y * 5
; Build square to mark spring location in edit area
p0 = [x+1, y]
p1 = [x+5, y+4]
POLYFILL, [p0[0], p1[0], p1[0], p0[0]], [p0[1], p0[1], p1[1], p1[1]], $
COLOR=GetColor(color), /DEVICE
END
;----------------------------------------
PRO DrawGrid
COMMON springCommon, cNumberOfFrames, cImageSize, cSpringStrength, $
cMaxSpringStrength, cGridSize, cMethodNames, $
cXAxisRotation, cZAxisRotation, cAxSlider, cAzSlider, $
cGrid, cViewDrawArea, cSpringDisplacement, cEditDrawArea, $
cEditDrawAreaID, cRenderMethod, cSpringWindow
WSET, cEditDrawArea
ERASE
FOR iy = 0, 160, 5 DO $
PLOTS,[0, 160], [iy, iy], COLOR=GetColor(180), /DEVICE ;Draw the grid
FOR ix= 0, 160, 5 DO $
PLOTS,[ix, ix], [0, 160], COLOR=GetColor(180), /DEVICE
FOR ix = 0, cGridSize-1 DO $
FOR iy = 0, cGridSize-1 DO BEGIN
IF (cGrid[ix, iy] LT 0.) OR (cGrid[ix, iy] GT 0.) THEN $
MarkSquare, ix[0], iy[0], 0
ENDFOR
END
PRO DrawShadedSquares, theScaledGrid, theDisplacementGrid, $
minDisplacement, maxDisplacement
COMMON springCommon
SURFR, AX=cXAxisRotation, AZ=cZAxisRotation ;Set the scaling
!X.S = [ 0, 1. / cGridSize ]
!Y.S = !X.S
!Z.S = [-minDisplacement, maxDisplacement] / $
(maxDisplacement - minDisplacement)
ERASE
del = 0.04 ;Fudge factor to cover surface
px = [ -del, 1.+del, 1.+del, -del] ;Basic polygon
py = [ -del, -del, 1.+del, 1.+del]
FOR iy = cGridSize-1, 0, -1 DO $
FOR ix = 0, cGridSize-1 DO $ ;Draw squares
POLYFILL, px+ix, py+iy, $
REPLICATE(theDisplacementGrid[ix, iy], 4), /T3D, $
COLOR=GetColor(theScaledGrid[ix,iy])
END
;----------------------------------------
; Draws spring frame
;
PRO DrawSurface, imageSize, DISPLACEMENTGRID=displacementGrid, $
VELOCITYGRID=velocityGrid, $
MAXDISPLACEMENT=maxDisplacement, MINDISPLACEMENT=minDisplacement, $
MAXVELOCITY=maxVelocity, MINVELOCITY=minVelocity
COMMON springCommon
rebinSize = (imageSize / cGridSize) * cGridSize
topColor = !D.TABLE_SIZE-1
CASE cRenderMethod OF ;Which rendering?
; Surface
0: SURFACE, displacementGrid, $
ZRANGE=[minDisplacement, maxDisplacement], $
AX=cXAxisRotation, AZ=cZAxisRotation
; Shaded surface (light source)
1: SHADE_SURF, displacementGrid, $
ZRANGE=[minDisplacement, maxDisplacement], $
AX=cXAxisRotation, AZ=cZAxisRotation
; Altitude shaded surface
2: SHADE_SURF, displacementGrid, SHADES=BYTSCL(displacementGrid, $
TOP=topColor, MIN=minDisplacement, MAX=maxDisplacement),$
ZRANGE=[minDisplacement, maxDisplacement], $
AX=cXAxisRotation, AZ=cZAxisRotation
; Velocity shaded surface
3: SHADE_SURF, displacementGrid, SHADES=BYTSCL(velocityGrid, $
TOP=topColor, MAX=maxVelocity, MIN=minVelocity),$
ZRANGE=[minDisplacement, maxDisplacement], $
AX=cXAxisRotation, AZ=cZAxisRotation
; Image of displacement
4: TV, REBIN(BYTSCL(displacementGrid, MAX=maxDisplacement, $
MIN = minDisplacement), rebinSize, rebinSize)
; Image of velocity
5: TV, REBIN(BYTSCL(velocityGrid, MAX=maxVelocity, $
MIN=minVelocity), rebinSize, rebinSize)
; Contour
6: CONTOUR, displacementGrid, LEVELS=FINDGEN(16.)/8.-1., XSTYLE=5, $
YSTYLE=5, C_COLORS=topColor * 0.5 * FINDGEN(16)/8.
; Squares by displacement
7: BEGIN
theScaledGrid = BYTSCL(displacementGrid, MIN=minDisplacement, $
MAX=maxDisplacement, TOP=topColor) ;shades
DrawShadedSquares, theScaledGrid, displacementGrid, $
minDisplacement, maxDisplacement
ENDCASE ; Squares by displacement
; Squares by velocity
8: BEGIN
theScaledGrid = BYTSCL(ABS(velocityGrid), MIN=0, MAX=maxVelocity, $
TOP=topColor)
DrawShadedSquares, theScaledGrid, displacementGrid, $
minDisplacement, maxDisplacement
ENDCASE ; Squares by velocity
ENDCASE
END
;----------------------------------------
; Does the calculations & drawing for spring animation
;
PRO DrawSpring, GROUP = group
COMMON springCommon
; Deactivate all window controls
WIDGET_CONTROL, cSpringWindow, SENSITIVE = 0
; Starting displacements, allow for border reflection
displacementGrid = FLTARR(cGridSize+2, cGridSize+2)
; Insert starting displacements
displacementGrid[1,1] = cGrid
; Starting velocity
velocityGrid = FLTARR(cGridSize+2, cGridSize+2)
; Set up animation
XINTERANIMATE, SET=[cImageSize, cImageSize, cNumberOfFrames], $
TITLE = cMethodNames[cRenderMethod], /SHOWLOAD, /CYCLE, /TRACK
currentWindow = !D.WINDOW
ERASE
; Do all at once, displacement
displacementFrames = FLTARR(cGridSize, cGridSize, cNumberOfFrames, /NOZERO)
velocityFrames = displacementFrames ;Velocity
; Make kernel for convolution
sq21 = 1./SQRT(2)
kernel = cSpringStrength * [[ sq21, 1, sq21], [1, 0, 1], [sq21, 1, sq21]]
kernel[1,1] = -TOTAL(kernel)
FOR iteration = 0, cNumberOfFrames-1 DO BEGIN ;Each iteration
; Calculate new velocity
velocityGrid = velocityGrid + CONVOL(displacementGrid, kernel)
; Calculate new displacement
displacementGrid = displacementGrid + velocityGrid
; Save for scaling
velocityFrames[0, 0, iteration] = velocityGrid[1:cGridSize, 1:cGridSize]
displacementFrames[0, 0, iteration] = $
displacementGrid[1:cGridSize, 1:cGridSize]
ENDFOR
; Get scaling
maxVelocity = MAX(velocityFrames, MIN=minVelocity)
maxDisplacement = MAX(displacementFrames, MIN=minDisplacement)
FOR iteration = 0, cNumberOfFrames-1 DO BEGIN ; Each frame
displacementGrid = displacementFrames[*,*,iteration]
velocityGrid = velocityFrames[*,*,iteration]
DrawSurface, cImageSize, DISPLACEMENTGRID=displacementGrid, $
VELOCITYGRID=velocityGrid, $
MAXDISPLACEMENT=maxDisplacement, MINDISPLACEMENT=minDisplacement, $
MAXVELOCITY=maxVelocity, MINVELOCITY=minVelocity
XINTERANIMATE, FRAME=iteration, WINDOW=currentWindow
ENDFOR
; Active the window controls again
WIDGET_CONTROL, cSpringWindow, SENSITIVE = 1
XINTERANIMATE, GROUP = group, 20
END
;----------------------------------------
PRO SpringEvent, event
COMMON springCommon
; Find the user value of the widget where the event occured
WIDGET_CONTROL, event.id, GET_UVALUE = widgetName
CASE widgetName OF
"METHOD_GROUP": BEGIN
cRenderMethod = event.index
; If render method is "Displacement Image" or "Velocity Image" or
; "Contour Plot" then disable x and z axis rotation since they're
; only 2 dimensional
IF (cRenderMethod GE 4 AND cRenderMethod LE 6) THEN BEGIN
WIDGET_CONTROL, cAxSlider, SENSITIVE=0
WIDGET_CONTROL, cAzSlider, SENSITIVE=0
ENDIF ELSE BEGIN
WIDGET_CONTROL, cAxSlider, SENSITIVE=1
WIDGET_CONTROL, cAzSlider, SENSITIVE=1
ENDELSE
swin = !D.WINDOW
WSET, cViewDrawArea
maxDisplacement = MAX(cGrid, MIN=minDisplacement)
DrawSurface, 192, DISPLACEMENTGRID=cGrid, VELOCITYGRID=cGrid, $
MAXDISPLACEMENT=maxDisplacement, MINDISPLACEMENT=minDisplacement, $
MAXVELOCITY=maxDisplacement, MINVELOCITY=minDisplacement
WSET, swin
ENDCASE
"KSPRING_SLIDER": cSpringStrength = event.value * cMaxSpringStrength / 100
"NUM_FRAMES_SLIDER": cNumberOfFrames = event.value
"MARK_DRAW_AREA": BEGIN
IF event.press EQ 0 THEN $
RETURN ; Ignore release
swin = !D.WINDOW
WSET, cEditDrawArea
p = [ event.x/5, event.y/5 ]
p[0] = FIX(p[0]) > 0 < (cGridSize-1)
p[1] = FIX(p[1]) > 0 < (cGridSize-1)
IF (cGrid[p[0], p[1]] EQ 0) THEN BEGIN ; Mark???
cGrid[p[0], p[1]] = cSpringDisplacement/100.
MarkSquare, p[0], p[1], 0 ; Draw in black mark
ENDIF ELSE BEGIN
cGrid[p[0], p[1]] = 0.
MarkSquare, p[0], p[1], !D.TABLE_SIZE-1 ; Erase old - with white mark
ENDELSE
WSET, cViewDrawArea
maxDisplacement = MAX(cGrid, MIN=minDisplacement)
DrawSurface, 192, DISPLACEMENTGRID=cGrid, VELOCITYGRID=cGrid, $
MAXDISPLACEMENT=maxDisplacement, MINDISPLACEMENT=minDisplacement, $
MAXVELOCITY=maxDisplacement, MINVELOCITY=minDisplacement
WSET, swin
ENDCASE
"HTSLIDER" : cSpringDisplacement = event.value
"AX_SLIDER" : BEGIN
cXAxisRotation = event.value
swin = !D.WINDOW
WSET, cViewDrawArea
maxDisplacement = MAX(cGrid, MIN=minDisplacement)
DrawSurface, 192, DISPLACEMENTGRID=cGrid, VELOCITYGRID=cGrid, $
MAXDISPLACEMENT=maxDisplacement, MINDISPLACEMENT=minDisplacement, $
MAXVELOCITY=maxDisplacement, MINVELOCITY=minDisplacement
WSET, swin
ENDCASE
"AZ_SLIDER" : BEGIN
cZAxisRotation = event.value
swin = !D.WINDOW
WSET, cViewDrawArea
maxDisplacement = MAX(cGrid, MIN=minDisplacement)
DrawSurface, 192, DISPLACEMENTGRID=cGrid, VELOCITYGRID=cGrid, $
MAXDISPLACEMENT=maxDisplacement, MINDISPLACEMENT=minDisplacement, $
MAXVELOCITY=maxDisplacement, MINVELOCITY=minDisplacement
WSET, swin
ENDCASE
"ANIMATE" : $
IF XREGISTERED("XInterAnimate") EQ 0 THEN $
DrawSpring, GROUP=event.top
"INFO" : BEGIN
infoText = [ $
"The Spring example is a dynamic simulation of a "+ $
"rectangular grid of weights connected by springs. The "+ $
"results may be visualized by a number of methods, "+ $
"illustrating some of the many ways of displaying data with IDL. ", "", $
"Pressing the Animate button starts the simulation from an "+ $
"initial starting grid. The initial Z position of the "+ $
'weights may be edited. To edit, set the "Spring Displacement"'+ $
"to the new Z value (range: -100 to 100), and click on the cell's position "+ $
"in the left hand grid. The X and "+ $
"Y position of the weights is fixed. The strength of "+ $
"the springs may be varied, as well as a number of "+ $
"viewing and simulation parameters. ", "", $
"WARNING: this example can easily exhaust the memory / swap "+ $
"space resources of small or improperly configured machines. ", "", $
"**** CONTROLS **** ", "", $
"Animate button: starts the simulation from the starting "+ $
"grid. Each frame is rendered and the XINTERANIMATE "+ $
"procedure is called to animate the results. ", "", $
"Info... button: Displays this text. ", "", $
"Rendering Methods: select a method, by clicking in the drop list. ", "", $
"Spring Strength slider: Sets the spring coefficient. A "+ $
"higher setting makes the springs stronger in relation "+ $
"to the weights. Higher settings result in more "+ $
"movement; lower settings result in smoother simulations. ", "", $
"X axis rotation slider: Controls the rotation about the "+ $
"X axis for the 3D displays. ", "", $
"Z axis rotation slider: Controls the rotation about the "+ $
"Z axis for 3D displays. ", "", $
"Number of frames: The number of animation frames in the "+ $
"animation. The amount of display memory is "+ $
"proportional to this number. WARNING: this demo can "+ $
"easily exhaust the memory / swap space resources of small machines. "]
ShowInfo, TITLE="Spring Example Information", GROUP=event.top, WIDTH=80,$
HEIGHT=24, INFOTEXT=infoText
ENDCASE
ELSE: $ ; When an event occurs in a widget that has no user value in this
; case statement, an error message is shown
MESSAGE, "Event User Value Not Found"
ENDCASE
END ;============= end of Spring event handling routine task =============
PRO CleanUpSpring, wSpringWindow
; Get the color table saved in the window's user value
WIDGET_CONTROL, wSpringWindow, GET_UVALUE=previousState
; Restore the previous color table.
TVLCT, previousState.colorTable
; Restore the previous background color.
!P.BACKGROUND = previousState.backgroundColor
; Restore the previous pen color.
!P.COLOR = previousState.penColor
END
;----------------------------------------
PRO Spring, GROUP = group
COMMON springCommon
IF XREGISTERED("Spring") THEN $
RETURN ;only one instance
IF XREGISTERED("XInterAnimate") THEN BEGIN
tmp = DIALOG_MESSAGE(/ERROR, ['Can''t run Surface Drawing Demo.', ' ', $
'Only one animation can be active at a time.' ])
RETURN
ENDIF
swin = !D.WINDOW
; Get the current color vectors to restore when this application is exited.
TVLCT, savedR, savedG, savedB, /GET
; Save items to be restored on exit in a structure
previousState = {colorTable: [[savedR],[savedG],[savedB]], $
backgroundColor: !P.BACKGROUND, $
penColor: !P.COLOR}
; Remove axis from all plots
!X.STYLE = 4
!Y.STYLE = 4
!Z.STYLE = 4
!X.MARGIN = 0
!Y.MARGIN = 0
; Set up defaults and constants:
IF N_ELEMENTS(cNumberOfFrames) LE 0 THEN BEGIN
cNumberOfFrames = 16 ; Initial values
cImageSize = 256 ; Size of spring animation draw widget
cMaxSpringStrength = 0.2 ; Largest possible spring const
cSpringStrength = 0.05 ; Initialize spring const
cGridSize = 32 ; Initialize grid size
cEditDrawAreaID = 0
cGrid = FLTARR(cGridSize, cGridSize) ; Starting grid
cGrid[cGridSize/3, cGridSize/3] = 1.
cSpringDisplacement = 100
cMethodNames = [ $
"Mesh Surface",$
"Light Source Shaded Surface", $
"Displacement Shaded Surface", $
"Velocity Shaded Surface",$
"Displacement Image",$
"Velocity Image",$
"Contour Plot", $
"Displacement Shaded Squares",$
"Velocity Shaded Squares"]
cXAxisRotation = 15 ;X axis rotation
cZAxisRotation = 20 ;Z axis rotation
ENDIF
; Initial rendering method is here to longest name to force
; menu to the largest size
cRenderMethod = 1
LOADCT, 0, /SILENT
; Initialize the background to white
!P.BACKGROUND = GetColor(!D.TABLE_SIZE-1)
; Initialize the pen color to black
!P.COLOR = GetColor(0)
; Create the main window
cSpringWindow = WIDGET_BASE(TITLE="Spring Example", XOFFSET=10, YOFFSET=10)
topBase = WIDGET_BASE(cSpringWindow, /COLUMN)
drawBase = WIDGET_BASE(topBase, /ROW)
gridBase = WIDGET_BASE(drawBase, /COLUMN)
editDrawLabel = WIDGET_LABEL(gridBase, VALUE='Click to add springs:')
cEditDrawAreaID = WIDGET_DRAW(gridBase, XSIZE=161, YSIZE=161, $
/BUTTON_EVENTS, RET=2, UVALUE='MARK_DRAW_AREA')
viewDrawAreaID = WIDGET_DRAW(drawBase, XSIZE=192, YSIZE=192, RET=2)
menuBase = WIDGET_BASE(topBase, /ROW)
; Create the method drop list
methodButtonBase = WIDGET_DROPLIST(menuBase, VALUE=cMethodNames, $
UVALUE='METHOD_GROUP', TITLE='Rendering Method:')
; Set the drop list to the current method
WIDGET_CONTROL, methodButtonBase, SET_DROPLIST_SELECT=cRenderMethod
controlBase = WIDGET_BASE(topBase, /COLUMN)
viewParameterBase = WIDGET_BASE(controlBase, /ROW)
displacementSlider = WIDGET_SLIDER(viewParameterBase, XSIZE=120, $
MINIMUM=-100, MAXIMUM=100, $
TITLE='Spring Displacement', $
VALUE=cSpringDisplacement, UVALUE='HTSLIDER')
cAxSlider = WIDGET_SLIDER(viewParameterBase, XSIZE=120, MINIMUM=-90, $
MAXIMUM=90, VALUE=cXAxisRotation, TITLE='X axis rotation', $
UVALUE="AX_SLIDER")
cAzSlider = WIDGET_SLIDER(viewParameterBase, XSIZE=120, MINIMUM=0, $
MAXIMUM=90, VALUE=cZAxisRotation, TITLE='Z axis rotation', $
UVALUE="AZ_SLIDER")
animateParameterBase = WIDGET_BASE(controlBase, /ROW)
strengthSlider = WIDGET_SLIDER(animateParameterBase, XSIZE=120, MINIMUM=1, $
MAXIMUM=100, $
VALUE=100*cSpringStrength/cMaxSpringStrength, $
TITLE='Spring Strength', UVALUE="KSPRING_SLIDER")
numFramesSlider = WIDGET_SLIDER(animateParameterBase, XSIZE=120, $
MINIMUM=2, MAXIMUM=40, VALUE=cNumberOfFrames, $'
TITLE='Number of frames', UVALUE="NUM_FRAMES_SLIDER")
; Add base and pushbuttons to Draw and Erase
PushButtonBase = WIDGET_BASE(animateParameterBase, /COLUMN, XPAD=20)
; Create "Animate" button
animateButton_w = WIDGET_BUTTON(PushButtonBase, VALUE='Animate',$
UVALUE='ANIMATE')
; Create "Info..." button
infoButton_w = WIDGET_BUTTON(PushButtonBase, VALUE='Info...', UVALUE='INFO')
; Display the window and save the previous color table in
; the user value to retore on exit
WIDGET_CONTROL, cSpringWindow, /REALIZE, SET_UVALUE=previousState
WIDGET_CONTROL, viewDrawAreaID, GET_VALUE = cViewDrawArea
WIDGET_CONTROL, cEditDrawAreaID, GET_VALUE = cEditDrawArea
DrawGrid ;Show the editing grid
WSET, cViewDrawArea
maxDisplacement = MAX(cGrid, MIN=minDisplacement)
DrawSurface, 192, DISPLACEMENTGRID=cGrid, VELOCITYGRID=cGrid, $
MAXDISPLACEMENT=maxDisplacement, MINDISPLACEMENT=minDisplacement, $
MAXVELOCITY=maxDisplacement, MINVELOCITY=minDisplacement
WSET, swin
XMANAGER, "Spring", cSpringWindow, EVENT_HANDLER = "SpringEvent", $
GROUP_LEADER = group, CLEANUP="CleanUpSpring", /NO_BLOCK
END